home *** CD-ROM | disk | FTP | other *** search
/ Gigarom 1 / Gigarom Macintosh Archives (Quantum Leap)(CDRM1080320)(1993).iso / FILES / DEV / I-Z / TransSkel.cpt / transSkelpas < prev   
Text File  |  1987-03-06  |  36KB  |  1,351 lines

  1.  
  2. {    TransSkel version 1.02 - Transportable application skeleton}
  3.  
  4. {    TransSkel is public domain and was originally written in LightSpeed C by:}
  5.  
  6. {            Paul DuBois}
  7. {            Wisconsin Regional Primate Research Center}
  8. {            1220 Capital Court}
  9. {            Madison WI  53706  USA}
  10.  
  11. {    UUCP:    allegra,ihnp4,seismo!uwvax!uwmacc!dubois}
  12. {    ARPA:    dubois@unix.macc.wisc.edu}
  13. {            dubois@rhesus.primate.wisc.edu}
  14.  
  15. {    The Pascal Version of TransSkel is public domain and was ported by        }
  16.  
  17. {            Owen Hartnett            }
  18. {            Ωhm Software            }
  19. {            163 Richard Drive        }
  20. {            Tiverton, RI 02878        }
  21.  
  22. {    CSNET:    omh@cs.brown.edu.CSNET                                             }
  23. {    ARPA:        omh%cs.brown.edu@relay.cs.net-relay.ARPA                        }
  24. {    UUCP:        [ihnp4,allegra]!brunix !omh                                            }
  25.  
  26. {    Psychic Wavelength:  182.2245 Meters  (sorry, couldn't resist)    }
  27.  
  28. {    This version of TransSkel written for Lightspeed Pascal.  Lightspeed Pascal is a}
  29. {    trademark of:}
  30. {            THINK Technologies, Inc}
  31. {            420 Bedford Street  Suite 350}
  32. {            Lexington, MA  02173  USA}
  33.  
  34. {  History}
  35. {  06/13/86    Beta version.}
  36. {  08/27/86    Version number changed to 1.01.}
  37. {              v1.0 DoGrow bug fixed - the port at the point of the}
  38. {              InvalRect could have been anything; the fix is to set}
  39. {              the port to the grown window first.  This also explains}
  40. {              why the kludge to DoActivate in v1.0 worked.}
  41. {  10/02/86    Version number changed to 1.02, as a result of adding}
  42. {            modifications by David W. Berry (well!dwb@lll-lcc.arpa)}
  43. {            for supporting window zooming.  Also used his modifications}
  44. {            for supporting modeless dialogs (though not in the same}
  45. {            form).  Dialogs can be #define'd on or off.}
  46. { 12/24/86  Finished final debugging of Pascal version. (well, final as they    }
  47. {            come.)  Dialogs cannot be defined off.    Santa Claus assists with final }
  48. {            modification.}
  49.  
  50. UNIT TransSkelpas;
  51.  
  52. INTERFACE
  53.  
  54.     PROCEDURE SkelInit;
  55.     PROCEDURE SkelMain;
  56.     PROCEDURE SkelWhoa;
  57.     PROCEDURE SkelClobber;
  58.     PROCEDURE SkelMenu (theMenu : MenuHandle;
  59.                                     pSelect : ProcPtr;
  60.                                     pClobber : ProcPtr);
  61.     PROCEDURE SkelRmveMenu (theMenu : MenuHandle);
  62.     PROCEDURE SkelApple (aboutTitle : Str255;
  63.                                     aboutProc : ProcPtr);
  64.     PROCEDURE SkelWindow (theWind : WindowPtr;
  65.                                     pMouse, pKey, pUpdate, pActivate, pClose, pClobber, pIdle : ProcPtr;
  66.                                     frontOnly : Boolean);
  67.     PROCEDURE SkelRmveWind (theWind : WindowPtr);
  68.     PROCEDURE SkelDialog (theDialog : DialogPtr;
  69.                                     pEvent, pClose, pClobber : ProcPtr);
  70.     PROCEDURE SkelRmveDlog (theDialog : DialogPtr);
  71.     PROCEDURE SkelGrowBounds (theWind : WindowPtr;
  72.                                     hLO, vLo, hHi, vHi : integer);
  73.     PROCEDURE SkelEventMask (mask : integer);
  74.     PROCEDURE SkelGetEventMask (mask : integer);
  75.     PROCEDURE SkelBackground (p : ProcPtr);
  76.     PROCEDURE SkelGetBackground (VAR p : ProcPtr);
  77.     PROCEDURE SkelEventHook (p : ProcPtr);
  78.     PROCEDURE SkelGetEventHook (VAR p : ProcPtr);
  79.     PROCEDURE SkelDlogMask (mask : integer);
  80.     PROCEDURE SkelGetDlogMask (VAR mask : integer);
  81.  
  82.  
  83.  
  84. IMPLEMENTATION
  85.     CONST
  86.         mBarHeight = 20;    { menu bar height.  All window sizing}
  87.  
  88. {    This window zooming stuff may need to be removed if you use the new Rom libraries        }
  89. {    if not, then you can add zooming without the overhead of the new Rom libs.  See TrackBox    }
  90. {     routine also.                                                                                            }
  91.  
  92.         inZoomIn = 7;
  93.         inZoomOut = 8;
  94. {    Window and Menu handler types, constants, variables.}
  95.  
  96. {    whList and mhList are the lists of window and menu handlers.}
  97. {    whClobOnRmve and mhClobOnRmve are true if the handler disposal proc}
  98. {    is to be called when a handler is removed.  They are temporarily set}
  99. {    false when handlers are installed for windows or menus that already}
  100. {    have handlers - the old handler is removed WITHOUT calling the}
  101. {    disposal proc.}
  102.  
  103. {    Default lower limits on window sizing of 80 pixels both directions is}
  104. {    sufficient to allow text windows room to draw a grow box and scroll}
  105. {    bars without having the thumb and arrows overlap.  These values may}
  106. {    be changed if such a constraint is undesirable with SkelGrowBounds.}
  107. {    Default upper limits are for the Macintosh, not the Lisa, but are set}
  108. {    per machine in SkelInit.}
  109.  
  110.     TYPE
  111.         WHandlerPtr = ^WHandler;
  112.         WHandlerHnd = ^WHandlerPtr;
  113.         WHandler = RECORD
  114.                 whWind : WindowPtr;    {window/dialog to be handled    }
  115.                 whClobber : ProcPtr;    { data structure disposal proc    }
  116.                 whMouse : ProcPtr;        { mouse-click handler proc        }
  117.                 whKey : ProcPtr;        { key-click handler proc            }
  118.                 whUpdate : ProcPtr;        { update handler proc                }
  119.                 whActivate : ProcPtr;    { activate event handler proc    }
  120.                 whClose : ProcPtr;        { close "event" handler proc        }
  121.                 whIdle : ProcPtr;            { main loop proc                    }
  122.                 whEvent : ProcPtr;        { dialog event proc                }
  123.                 whGrow : Rect;            { limits on window sizing        }
  124.                 whSized : Boolean;        { true = window was resized    }
  125.                 whFrontOnly : Boolean;    { true = idle only when active    }
  126.                 whNext : WHandlerHnd;            { next window handler            }
  127.             END;
  128.  
  129.         MHandlerPtr = ^MHandler;
  130.         MHandlerHnd = ^MHandlerPtr;
  131.  
  132.         MHandler = RECORD
  133.                 mhID : integer;                { menu id                                    }
  134.                 mhSelect : ProcPtr;            { item selection handler proc            }
  135.                 mhClobber : ProcPtr;        { menu disposal handler proc            }
  136.                 mhNext : MHandlerHnd;        { next menu handler                        }
  137.             END;
  138.  
  139.         EventPtr = ^EventRecord;
  140.     VAR
  141.         whList : WHandlerHnd;                { list of menu handlers }
  142.         whClobOnRmve : Boolean;
  143.         growRect : Rect;
  144.         mhList : MHandlerHnd;
  145.         mhClobOnRmve : Boolean;
  146.  
  147. {    Variables for default Apple menu handler.  appleID is set to 1 if}
  148. {    SkelApple is called and is the id of the Apple menu, appleAboutProc}
  149. {    is the procedure to execute if there is an About... item and it's}
  150. {    chosen from the Apple menu.  If doAbout is true, then the menu}
  151. {    contains the About... item, otherwise it's just desk accessories.}
  152.  
  153.         appleMenu : MenuHandle;
  154.         appleID : integer;
  155.         appleAboutProc : ProcPtr;
  156.         doAbout : Boolean;
  157.  
  158. {    Miscellaneous}
  159.  
  160. {    screenPort points to the window manager port.}
  161.  
  162. {    doneFlag determines when SkelMain returns.  It is set by calling}
  163. {    SkelWhoa(), which the host does to request a halt.}
  164.  
  165. {    pBkgnd points to a background procedure, to be run during event}
  166. {    processing.  Set it with SkelBackground.  If nil, there's no}
  167. {    procedure.}
  168.  
  169. {    pEvent points to an event-inspecting hook, to be run whenever an}
  170. {    event occurs.  Set it with SkelEventHook.  If nil, there's no}
  171. {    procedure.}
  172.  
  173. {    eventMask controls the event types requested in the GetNextEvent}
  174. {    call in SkelMain.}
  175.  
  176. {    diskInitPt is the location at which the disk initialization dialog}
  177. {    appears, if an uninitialized disk is inserted.}
  178.  
  179.         screenPort : GrafPtr;
  180.         doneFlag : integer;
  181.         pBkgnd : ProcPtr;
  182.         pEvent : ProcPtr;
  183.         eventMask : integer;
  184.         diskInitPt : Point;
  185.  
  186. {    Events that are passed to dialogs.  Others are ignored.}
  187. {    Standard mask passes , mousedown, keydown, autokey, update,}
  188. {    activate and null events.  Null events are controlled by bit 0.}
  189.  
  190.         dlogEventMask : integer;
  191.         pEventflag : Boolean;
  192.  
  193. { Rather than including the entire new ROM libraries, with all the other stuff you might not use    }
  194. { I've instead included just the Zoom box stuff here.  Depending on your status, you can either    }
  195. { leave things as they are, and only use zooming from the new Rom libs, or comment out the        }
  196. { calls, and include the new Rom libraries if you want to incorporate other new Rom calls        }
  197.  
  198.     FUNCTION TrackBox (theWindow : WindowPtr;
  199.                                     thePt : Point;
  200.                                     partCode : INTEGER) : BOOLEAN;
  201.     INLINE
  202.         $A83B;
  203.  
  204. { -------------------------------------------------------------------- }
  205. {                        Internal (private) Routines                                    }
  206. { -------------------------------------------------------------------- }
  207.  
  208.  
  209.  
  210. {    Get handler associated with user or dialog window.}
  211. {    Return nil if window doesn't belong to any known handler.}
  212. {    This routine is absolutely fundamental to TransSkel.}
  213.  
  214.     FUNCTION GetWDHandler (theWind : WindowPtr) : WHandlerHnd;
  215.  
  216.         VAR
  217.             h : WHandlerHnd;
  218.     BEGIN
  219.         h := WhList;
  220.         GetWDHandler := NIL;
  221.         WHILE h <> NIL DO
  222.             IF h^^.whWind = theWind THEN
  223.                 BEGIN
  224.                     GetWDHandler := h;
  225.                     h := NIL;
  226.                 END
  227.             ELSE
  228.                 h := WHandlerHnd(h^^.whNext);
  229.     END;
  230.  
  231.     FUNCTION GetWHandler (theWind : WindowPtr) : WHandlerHnd;
  232.  
  233.         VAR
  234.             h : WHandlerHnd;
  235.             myPeek : WindowPeek;
  236.  
  237.     BEGIN
  238.         h := GetWDHandler(theWind);
  239.         myPeek := WindowPeek(theWind);
  240.         IF h <> NIL THEN
  241.             BEGIN
  242.                 IF mypeek^.windowKind <> dialogKind THEN
  243.                     GetWHandler := h;
  244.             END
  245.         ELSE
  246.             GetWHandler := NIL;
  247.     END;
  248.  
  249. {    Get handler associated with dialog window.}
  250. {    Return nil if window doesn't belong to any known handler.}
  251. {    The order of the two tests is critical:  theDialog might be nil.}
  252.  
  253.     FUNCTION GetDHandler (theDialog : WindowPtr) : WHandlerHnd;
  254.  
  255.         VAR
  256.             h : WHandlerHnd;
  257.             myPeek : WindowPeek;
  258.  
  259.     BEGIN
  260.         h := GetWDHandler(theDialog);
  261.         myPeek := WindowPeek(theDialog);
  262.         IF h <> NIL THEN
  263.             BEGIN
  264.                 IF mypeek^.windowKind = dialogKind THEN
  265.                     GetDHandler := h;
  266.             END
  267.         ELSE
  268.             GetDHandler := NIL;
  269.     END;
  270.  
  271. {The following procedures are Pascal "glue" that allows Pascal to call a Procedure    }
  272. { from a ProcPtr.  It is similar to (*p) () construct used in the C dialect.  Different    }
  273. { procedures are necessary for the reason of Pascal's strongly typed parameter        }
  274. { list.  Fortunately, there are not too many calls which use different param lists        }
  275.  
  276.     PROCEDURE callpMouse (thePoint : Point;
  277.                                     theTime : longint;
  278.                                     theMods : integer;
  279.                                     myProc : ProcPtr);
  280.  
  281.     INLINE
  282.         $205f,     {movea.l  (a7)+,a0        ; (a0) is a ptr to string, 4(a0) is mode}
  283.         $4e90;
  284.  
  285.     PROCEDURE callpKey (theChar : char;
  286.                                     theMods : integer;
  287.                                     myProc : ProcPtr);
  288.  
  289.     INLINE
  290.         $205f,     {movea.l  (a7)+,a0        ; (a0) is a ptr to string, 4(a0) is mode}
  291.         $4e90;
  292.  
  293.     PROCEDURE callpEvent (theitem : integer;
  294.                                     theEvent : EventPtr;
  295.                                     myProc : ProcPtr);
  296.  
  297.     INLINE
  298.         $205f,     {movea.l  (a7)+,a0        ; (a0) is a ptr to string, 4(a0) is mode}
  299.         $4e90;
  300.  
  301.     FUNCTION callotherEvent (theEvent : EventPtr;
  302.                                     myProc : ProcPtr) : Boolean;
  303.  
  304.     INLINE
  305.         $205f, $4e90;
  306.  
  307.  
  308.     PROCEDURE callpBoolean (myBool : Boolean;
  309.                                     myProc : ProcPtr);
  310.  
  311. { Two calls use Booleans as one parameter arguments.  This procedure handles    }
  312. { both of them.                                                                            }
  313.  
  314.     INLINE
  315.         $205f,     {movea.l  (a7)+,a0        ; (a0) is a ptr to string, 4(a0) is mode}
  316.         $4e90;
  317.  
  318.     PROCEDURE callpInt (myInt : integer;
  319.                                     myProc : ProcPtr);
  320.  
  321. { Two calls use Booleans as one parameter arguments.  This procedure handles    }
  322. { both of them.                                                                            }
  323.  
  324.     INLINE
  325.         $205f,     {movea.l  (a7)+,a0        ; (a0) is a ptr to string, 4(a0) is mode}
  326.         $4e90;
  327.  
  328.     PROCEDURE callpMenu (myMenu : MenuHandle;
  329.                                     myProc : ProcPtr);
  330.  
  331. { Handle removeal of menus.     }
  332.  
  333.     INLINE
  334.         $205f,     {movea.l  (a7)+,a0        ; (a0) is a ptr to string, 4(a0) is mode}
  335.         $4e90;
  336.  
  337.     PROCEDURE callpnoarg (myProc : ProcPtr);
  338.  
  339. { For all the Procedures that are called with no arguments                            }
  340.  
  341.     INLINE
  342.         $205f,     {movea.l  (a7)+,a0        ; (a0) is a ptr to string, 4(a0) is mode}
  343.         $4e90;
  344.  
  345. {    General menu-handler.  Just passes selection to the handler's}
  346. {    select routine.  If the select routine is nil, selecting items from}
  347. {    the menu is a nop.}
  348.  
  349.     PROCEDURE DoMenuCommand (command : longint);
  350.  
  351.         VAR
  352.             menu : integer;
  353.             item : integer;
  354.             mh : MHandlerHnd;
  355.             p : ProcPtr;
  356.  
  357.     BEGIN
  358.         menu := HiWord(command);
  359.         item := LoWord(command);
  360.         mh := mhList;
  361.         WHILE (mh <> NIL) DO
  362.             BEGIN
  363.                 p := mh^^.mhSelect;
  364.                 IF ((menu = mh^^.mhID) AND (p <> NIL)) THEN
  365.                     BEGIN
  366.                         callpInt(item, p);
  367.                         mh := NIL;
  368.                     END
  369.                 ELSE
  370.                     mh := mh^^.mhNext;
  371.             END;
  372.         HiliteMenu(0);
  373.     END;
  374.  
  375. {    Apple menu handler}
  376.  
  377. {    DoAppleItem:  If the first item was chosen, and there's an "About..."}
  378. {    item, call the procedure associated with it (if not nil).  If there}
  379. {    is no "About..." item or the item was not the first one, then open}
  380. {    the associated desk accessory.  The port is saved and restored}
  381. {    because OpenDeskAcc does not always preserve it correctly.}
  382.  
  383. {    DoAppleClobber disposes of the Apple menu.}
  384.  
  385.     PROCEDURE DoAppleItem (item : integer);
  386.  
  387.         VAR
  388.             curPort : GrafPtr;
  389.             str : Str255;
  390.             ignore : integer;
  391.  
  392.     BEGIN
  393.         IF doAbout AND (item = 1) THEN
  394.             BEGIN
  395.                 IF appleAboutProc <> NIL THEN
  396.                     callpnoarg(appleAboutProc);
  397.             END
  398.         ELSE
  399.             BEGIN
  400.                 GetPort(curPort);
  401.                 GetItem(appleMenu, item, str);
  402.                 ignore := OpenDeskAcc(str);
  403.                 SetPort(curPort);
  404.             END;
  405.     END;
  406.  
  407.     PROCEDURE DoAppleClobber;
  408.     BEGIN
  409.         DisposeMenu(appleMenu);
  410.     END;
  411.  
  412. { --------------------------------------------------------------------     }
  413. {                        Window-handler routing routines                            }
  414. {                                                                                        }
  415. {    Each routine sets the port to the handler's window before executing        }
  416. {    the handler procedure.                                                            }
  417. { --------------------------------------------------------------------     }
  418.  
  419.  
  420. {    Pass local mouse coordinates, click time, and the modifiers flag}
  421. {    word to the handler.}
  422.  
  423.     PROCEDURE DoMouse (h : WHandlerHnd;
  424.                                     theEvent : EventPtr);
  425.  
  426.         VAR
  427.             p : ProcPtr;
  428.             thePt : Point;
  429.  
  430.     BEGIN
  431.         IF (h <> NIL) THEN
  432.             BEGIN
  433.                 SetPort(h^^.whWind);
  434.                 p := h^^.whMouse;
  435.                 IF p <> NIL THEN
  436.                     BEGIN
  437.                         thePt := theEvent^.where;
  438.                         GlobalToLocal(thePt);
  439.                         callpMouse(thePt, theEvent^.when, theEvent^.modifiers, p);
  440.                     END;
  441.             END;
  442.     END;
  443.  
  444. {    Pass the character and the modifiers flag word to the handler.}
  445.  
  446.     PROCEDURE DoKey (h : WHandlerHnd;
  447.                                     ch : char;
  448.                                     mods : integer);
  449.         VAR
  450.             p : ProcPtr;
  451.  
  452.     BEGIN
  453.         IF h <> NIL THEN
  454.             BEGIN
  455.                 SetPort(h^^.whWind);
  456.                 p := h^^.whKey;
  457.                 IF p <> NIL THEN
  458.                     callpKey(ch, mods, p);
  459.             END;
  460.     END;
  461.  
  462.     PROCEDURE DoUpdate (h : WHandlerHnd);
  463.  
  464.         VAR
  465.             rh : WhandlerHnd;
  466.             p : ProcPtr;
  467.             updPort, tmpPort : GrafPtr;
  468.  
  469.     BEGIN
  470.         rh := h;
  471.         IF rh <> NIL THEN
  472.             BEGIN
  473.                 GetPort(tmpPort);
  474.                 updPort := rh^^.whWind;
  475.                 SetPort(updPort);
  476.                 BeginUpdate(updPort);
  477.                 p := rh^^.whUpdate;
  478.                 IF p <> NIL THEN
  479.                     BEGIN
  480.                         callpBoolean(rh^^.whSized, p);
  481.                         rh^^.whSized := false;
  482.                     END;
  483.                 EndUpdate(updPort);
  484.                 SetPort(tmpPort);
  485.             END;
  486.     END;
  487.  
  488.     PROCEDURE DoActivate (h : WHandlerHnd;
  489.                                     active : Boolean);
  490.  
  491.         VAR
  492.             p : ProcPtr;
  493.  
  494.     BEGIN
  495.         IF h <> NIL THEN
  496.             p := h^^.whActivate
  497.         ELSE
  498.             p := NIL;
  499.         IF (h <> NIL) AND (p <> NIL) THEN
  500.             BEGIN
  501.                 SetPort(h^^.whWind);
  502.                 callpBoolean(active, p);
  503.             END;
  504.     END;
  505.  
  506. {    Execute a window handler's close proc.  This may be used by handlers}
  507. {    for temp windows that want to remove themselves when the window}
  508. {    is closed:  they can call SkelRmveWind to dispose of the window}
  509. {    and remove the handler from the window handler list.  Thus, windows}
  510. {    may be dynamically created and destroyed without filling up the}
  511. {    handler list with a bunch of invalid handlers.}
  512.  
  513. {    If the handler doesn't have a close proc, just hide the window.}
  514. {    The host should provide some way of reopening the window (perhaps}
  515. {    a menu selection).  Otherwise the window will be lost from user}
  516. {    control if it is hidden, since it won't receive user events.}
  517.  
  518. {    The port is set to the window manager port after calling the}
  519. {    handler proc, to avoid a dangling port.}
  520.  
  521. {    This is called both for regular and dialog windows.}
  522.  
  523.     PROCEDURE DoClose (h : WHandlerHnd);
  524.  
  525.         VAR
  526.             rh : WHandlerHnd;
  527.             p : ProcPtr;
  528.     BEGIN
  529.         rh := h;
  530.         IF rh <> NIL THEN
  531.             BEGIN
  532.                 SetPort(rh^^.whWind);
  533.                 p := rh^^.whClose;
  534.                 IF (p <> NIL) THEN
  535.                     callpnoarg(p)
  536.                 ELSE
  537.                     HideWindow(rh^^.whWind);
  538.                 SetPort(screenPort);
  539.             END;
  540.     END;
  541.  
  542.     PROCEDURE DoClobber (h : WHandlerHnd);
  543.  
  544.         VAR
  545.             p : ProcPtr;
  546.     BEGIN
  547.         IF (h <> NIL) THEN
  548.             BEGIN
  549.                 SetPort(h^^.whWind);
  550.                 p := h^^.whClobber;
  551.                 IF p <> NIL THEN
  552.                     callpnoarg(p);
  553.                 SetPort(screenPort);
  554.             END;
  555.     END;
  556.  
  557.     PROCEDURE DoIdle (h : WHandlerHnd);
  558.  
  559.         VAR
  560.             p : ProcPtr;
  561.             tmpPort : GrafPtr;
  562.     BEGIN
  563.         IF (h <> NIL) THEN
  564.             BEGIN
  565.                 GetPort(tmpPort);
  566.                 SetPort(h^^.whWind);
  567.                 p := h^^.whIdle;
  568.                 IF (p <> NIL) THEN
  569.                     callpnoarg(p);
  570.                 SetPort(tmpPort);
  571.             END;
  572.     END;
  573.  
  574.  
  575. {    Handle event if it's for a dialog.  The event must be one of}
  576. {    those that is passed to dialogs according to dlogEventMask.}
  577. {    This mask can be set so that disk-inserts, for instance, don't}
  578. {    get eaten up.}
  579.  
  580.     FUNCTION DoDialog (theEvent : EventPtr) : Boolean;
  581.  
  582.         VAR
  583.             dh : WHandlerHnd;
  584.             theDialog : DialogPtr;
  585.             what : integer;
  586.             item : integer;
  587.             tmpPort : GrafPtr;
  588.             ignore : Boolean;
  589.             testme : longint;
  590.  
  591.     BEGIN
  592.  
  593. {    handle command keys before they get to IsDialogEvent}
  594.  
  595.         what := theEvent^.what;
  596.         testme := BitShift(longint(1), what);
  597.         testme := BitAnd(testme, longint(dlogEventMask));
  598.         IF (((what = keydown) OR (what = autokey)) AND Boolean(BitAnd(theEvent^.modifiers, cmdkey))) THEN
  599.             BEGIN
  600.                 DoMenuCommand(MenuKey(Char(BitAnd(theEvent^.message, charCodeMask))));
  601.                 DoDialog := true;
  602.             END
  603.         ELSE IF testme > 0 THEN
  604.  
  605.             IF IsDialogEvent(theEvent^) THEN
  606.                 BEGIN
  607.                     IF DialogSelect(theEvent^, theDialog, item) THEN
  608.                         BEGIN
  609.                             dh := WHandlerHnd(GetDHandler(theDialog));
  610.                             IF (dh <> NIL) THEN
  611.                                 IF (dh^^.whEvent <> NIL) THEN
  612.                                     BEGIN
  613.                                         GetPort(tmpPort);
  614.                                         SetPort(theDialog);
  615.                                         callpEvent(item, theEvent, dh^^.whEvent);
  616.                                         SetPort(tmpPort);
  617.                                     END;
  618.                         END;
  619.                     DoDialog := true;
  620.                 END
  621.             ELSE
  622.                 DoDialog := false;
  623.     END;
  624.  
  625.  
  626. { -------------------------------------------------------------------- }
  627. {                            Event-handling routines                        }
  628. { -------------------------------------------------------------------- }
  629.  
  630. {    Have either sized or zoomed the window.  Invalidate it to force}
  631. {    an update and set the 'resized' flag in the window handler true.}
  632.  
  633.     PROCEDURE TriggerUpdate (h : WHandlerHnd;
  634.                                     thePort : GrafPtr);
  635.  
  636.     BEGIN
  637.         SetPort(thePort);
  638.         InvalRect(thePort^.portRect);
  639.         IF (h <> NIL) THEN
  640.             BEGIN
  641.                 h^^.whSized := true;
  642.             END;
  643.     END;
  644.  
  645. {    Size a window.  If the window has a handler, use the grow limits}
  646. {    in the handler record, otherwise use the defaults.}
  647.  
  648. {    The portRect is invalidated to force an update event.  (The port}
  649. {    must be set first, as it could be pointing anywhere.)  The handler's}
  650. {    update procedure should check the parameter passed to it to check}
  651. {    whether the window has changed size, if it needs to adjust itself to}
  652. {    the new size.  THIS IS A CONVENTION.  Update procs must notice grow}
  653. {    "events", there is no procedure specifically for such events.}
  654.  
  655. {    The clipping rectangle is not reset.  If the host application}
  656. {    keeps the clipping set equal to the portRect or something similar,}
  657. {    then it will have to arrange to treat window growing with more}
  658. {    care.}
  659.  
  660.     PROCEDURE DoGrow (h : WHandlerHnd;
  661.                                     thePort : GrafPtr;
  662.                                     StartPt : Point);
  663.  
  664.         VAR
  665.             r : Rect;
  666.             growRes : longint;
  667.  
  668.     BEGIN
  669.         IF (h <> NIL) THEN
  670.             BEGIN
  671.                 r := h^^.whGrow;
  672.             END
  673.         ELSE
  674.             r := growRect;
  675.         growRes := GrowWindow(thePort, startPt, r);
  676.         IF growRes <> 0 THEN
  677.             BEGIN
  678.                 SizeWindow(thePort, LoWord(growRes), HiWord(growRes), false);
  679.                 TriggerUpdate(h, thePort);
  680.             END;
  681.     END;
  682.  
  683. { Remove following procedure if using new rom library    }
  684.  
  685.     PROCEDURE ZoomWindow (theWindow : GrafPtr;
  686.                                     partCode : INTEGER;
  687.                                     front : BOOLEAN);
  688.     INLINE
  689.         $A83A;
  690.  
  691. {    Zoom the current window.  Very similar to DoGrow}
  692.  
  693.     PROCEDURE DoZoom (h : WHandlerHnd;
  694.                                     thePort : GrafPtr;
  695.                                     partcode : integer);
  696.  
  697.     BEGIN
  698.         ZoomWindow(thePort, partcode, false);
  699.         TriggerUpdate(h, thePort);
  700.     END;
  701.  
  702. {    General event handler}
  703.  
  704.     PROCEDURE DoEvent (theEvt : EventPtr);
  705.  
  706.         VAR
  707.             theEvent : EventPtr;
  708.             evtPt : Point;
  709.             evtPort : GrafPtr;
  710.             evtPart : integer;
  711.             evtChar : char;
  712.             evtMods : integer;
  713.             h : WHandlerHnd;
  714.             r : Rect;
  715.             ignore : integer;
  716.  
  717.     BEGIN
  718.         theEvent := theEvt;
  719.         IF (DoDialog(theEvent)) THEN
  720.             BEGIN
  721.             END
  722.         ELSE
  723.             BEGIN
  724.                 evtPt := theEvent^.where;
  725.                 CASE theEvent^.what OF
  726.                     nullEvent : 
  727.                         ;
  728.  
  729. {    Mouse click.  Get the window that the click occurred in, and the}
  730. {    part of the window.}
  731.  
  732.                     mouseDown : 
  733.                         BEGIN
  734.                             evtPart := FindWindow(evtPt, evtPort);
  735.                             h := GetWHandler(evtPort);
  736.                             CASE evtPart OF
  737.  
  738. {    Click in a desk accessory window.  Pass back to the system.}
  739.  
  740.                                 inSysWindow : 
  741.                                     SystemClick(theEvent^, evtPort);
  742.  
  743. {    Click in menu bar.  Track the mouse and execute selected command,}
  744. {    if any.}
  745.  
  746.                                 inMenuBar : 
  747.                                     DoMenuCommand(MenuSelect(evtPt));
  748.  
  749. {    Click in grow box.  Resize window.}
  750.  
  751.                                 inGrow : 
  752.                                     DoGrow(h, evtPort, evtPt);
  753.  
  754. {    Click in title bar.  Drag the window around.  Leave at least}
  755. {    4 pixels visible in both directions.}
  756.  
  757.                                 inDrag : 
  758.                                     BEGIN
  759.                                         r := screenPort^.portRect;
  760.                                         r.top := r.top + mBarHeight;        { Skip down past menu bar    }
  761.                                         InsetRect(r, 4, 4);
  762.                                         DragWindow(evtPort, evtPt, r);
  763.                                     END;
  764.  
  765. {    Click in close box.  Call the close proc if the window has one.}
  766.  
  767.                                 inGoAway : 
  768.                                     IF (TrackGoAway(evtPort, evtPt)) THEN
  769.                                         DoClose(GetWDHandler(evtPort));
  770.  
  771. {    Click in content region.  If the window wasn't frontmost (active),}
  772. {    just select it, otherwise pass the click to the window's mouse}
  773. {    click handler.}
  774.  
  775.                                 inContent : 
  776.                                     IF (evtPort <> FrontWindow) THEN
  777.                                         SelectWindow(evtPort)
  778.                                     ELSE
  779.                                         DoMouse(h, theEvent);
  780.  
  781. {    Click in zoom box.  Track the click and then zoom the window if}
  782. {    necessary}
  783.  
  784.                                 inZoomin, inZoomOut : 
  785.                                     IF (TrackBox(evtPort, evtPt, evtPart)) THEN
  786.                                         DoZoom(h, evtport, evtPart);
  787.                                 OTHERWISE
  788.                                     ;
  789.                             END;{mousedown}
  790.                         END;
  791.  
  792. {    Key event.  If the command key was down, process as menu item}
  793. {    selection, otherwise pass the character and the modifiers flags}
  794. {    to the active window's key handler.}
  795.  
  796. {    If dialogs are supported, there's no check for command-key}
  797. {    equivalents, since that would have been checked in DoDialog.}
  798.  
  799.                     keydown, autokey : 
  800.                         BEGIN
  801.                             evtChar := char(BitAnd(theEvent^.message, charCodeMask));
  802.                             evtMods := theEvent^.modifiers;
  803.                             IF BitAnd(evtMods, cmdKey) > 0 THEN
  804.                                 DoMenuCommand(menuKey(evtChar))
  805.                             ELSE
  806.                                 DoKey(GetWHandler(FrontWindow), evtChar, evtMods);
  807.                         END;
  808.  
  809. {    Update a window.}
  810.  
  811.                     updateEvt : 
  812.                         DoUpdate(GetWHandler(WindowPtr(theEvent^.message)));
  813.  
  814. {    Activate or deactivate a window.}
  815.  
  816.                     activateEvt : 
  817.                         DoActivate(GetWHandler(WindowPtr(theEvent^.message)), (BitAnd(theEvent^.modifiers, activeFlag) <> 0));
  818.  
  819. {    handle inserts of uninitialized disks}
  820.  
  821.                     diskEvt : 
  822.                         IF (HiWord(theEvent^.message) <> noErr) THEN
  823.                             BEGIN
  824.                                 DILoad;
  825.                                 ignore := DIBadMount(diskInitPt, theEvent^.message);
  826.                                 DIUnload;
  827.                             END;
  828.                     OTHERWISE
  829.                 END;
  830.             END;
  831.     END;
  832.  
  833. { -------------------------------------------------------------------- }
  834. {                        Interface (public) Routines                        }
  835. { -------------------------------------------------------------------- }
  836.  
  837.  
  838. {    Initialize the various Macintosh Managers.}
  839. {    Set default upper limits on window sizing.}
  840. {    FlushEvents does NOT toss disk insert events, so that disks}
  841. {    inserted while the application is starting up don't result}
  842. {    in dead drives.}
  843.  
  844.     PROCEDURE SkelInit;
  845.     BEGIN
  846.         InitCursor;
  847.         whList := NIL;
  848.         whClobOnRmve := true;
  849.         SetRect(growRect, 80, 80, 512, 342 - mBarHeight);
  850.         mhList := NIL;
  851.         mhClobOnRmve := true;
  852.         appleID := 0;
  853.         appleAboutProc := NIL;
  854.         doAbout := false;
  855.         doneflag := 0;
  856.         pBkgnd := NIL;
  857.         pEvent := NIL;
  858.         pEventflag := false;
  859.         eventmask := everyEvent;
  860.         diskInitPt.v := 120;
  861.         diskInitPt.h := 100;
  862.         dlogEventMask := $16b;
  863.  
  864. {    Set upper limits of window sizing to machine screen size.  Allow}
  865. {    for the menu bar.}
  866.  
  867.         GetWMgrPort(screenport);
  868.         growRect.right := screenPort^.portRect.right;
  869.         growRect.bottom := screenPort^.portRect.bottom - mBarHeight;
  870.     END;
  871.  
  872. {    Main loop.}
  873.  
  874. {    Task care of DA's with SystemTask.}
  875. {    Run background task if there is one.}
  876. {    If there is an event, check for an event hook.  If there isn't}
  877. {    one defined, or if there is but it returns false, call the}
  878. {    general event handler.  (Hook returns true if TransSkel should}
  879. {    ignore the event.)}
  880. {    If no event, call the "no-event" handler for the front window and for}
  881. {    any other windows with idle procedures that are always supposed}
  882. {    to run.  This is done in such a way that it is safe for idle procs}
  883. {    to remove the handler for their own window if they want (unlikely,}
  884. {    but...)  This loop doesn't check whether the window is really}
  885. {    a dialog window or not, but it doesn't have to, because such}
  886. {    things always have a nil idle proc.}
  887. {    }
  888. {    doneFlag is reset upon exit.  This allows it to be called}
  889. {    repeatedly, or recursively.}
  890.  
  891. {    If dialogs are supported, null events are looked at (in SkelMain)}
  892. {    and passed to the event handler.  This is necessary to make sure}
  893. {    DialogSelect gets called repeatedly, or the caret won't blink if}
  894. {    a dialog has any editText items.}
  895.  
  896. {    If an event-inspecting hook is installed, null events are not passed}
  897. {    to it.}
  898.  
  899.     PROCEDURE SkelMain;
  900.  
  901.         VAR
  902.             theEvent : EventRecord;
  903.             wh, wh2 : WHandlerHnd;
  904.             w : WindowPtr;
  905.             haveEvent, testpevent, testbool : Boolean;
  906.  
  907.     BEGIN
  908.         WHILE (doneFlag = 0) DO
  909.             BEGIN
  910.                 SystemTask;
  911.                 IF (pBkgnd <> NIL) THEN
  912.                     callpnoarg(pBkgnd);
  913.                 haveEvent := GetNextEvent(eventMask, theEvent);
  914.                 IF (pEvent <> NIL) THEN
  915.                     testpevent := CallotherEvent(@theEvent, pEvent)
  916.                 ELSE
  917.                     testpevent := false;
  918.                 testbool := haveEvent AND (testpevent = false);
  919.                 IF ((pEvent = NIL) OR testbool) THEN
  920.                     DoEvent(@theEvent);
  921.                 IF NOT haveEvent THEN
  922.                     BEGIN
  923.                         wh := whList;
  924.                         WHILE (wh <> NIL) DO
  925.                             BEGIN
  926.                                 wh2 := wh^^.whNext;
  927.                                 w := wh^^.whWind;
  928.                                 IF ((w = FrontWindow) OR NOT wh^^.whFrontOnly) THEN
  929.                                     BEGIN
  930.                                         SystemTask;
  931.                                         DoIdle(wh);
  932.                                     END;
  933.                                 wh := wh2;
  934.                             END;
  935.                     END;
  936.             END;
  937.         doneFlag := 0;
  938.     END;
  939.  
  940. {    Tell SkelMain to stop}
  941.  
  942.     PROCEDURE SkelWhoa;
  943.     BEGIN
  944.         doneFlag := 1;
  945.     END;
  946.  
  947. {    Clobber all the menu, window and dialog handlers}
  948.  
  949.     PROCEDURE SkelClobber;
  950.  
  951.  
  952.     BEGIN
  953.         WHILE (whList <> NIL) DO
  954.             BEGIN
  955.                 SkelRmveWind(whList^^.whWind);
  956.             END;
  957.         WHILE (mhList <> NIL) DO
  958.             BEGIN
  959.                 SkelRmveMenu(GetMHandle(mhList^^.mhID));
  960.             END;
  961.     END;
  962.  
  963. { -------------------------------------------------------------------- }
  964. {                        Menu-handler interface routines                            }
  965. { -------------------------------------------------------------------- }
  966.  
  967.  
  968.  
  969.  
  970. {    Install handler for a menu.  Remove any previous handler for it.}
  971. {    Pass the following parameters:}
  972.  
  973. {    theMenu    Handle to the menu to be handled.  Must be created by host.}
  974. {    pSelect    Proc that handles selection of items from menu.  If this is}
  975. {            nil, the menu is installed, but nothing happens when items}
  976. {            are selected from it.}
  977. {    pClobber Proc for disposal of handler's data structures.  Usually}
  978. {            nil for menus that remain in menu bar until program}
  979. {            termination.}
  980.  
  981. {    The menu is installed and drawn in the menu bar.}
  982.  
  983.     PROCEDURE SkelMenu;
  984.         VAR
  985.             mh : MHandlerHnd;
  986.             myHand : Handle;
  987.     BEGIN
  988.         mhClobOnRmve := false;
  989.         SkelRmveMenu(theMenu);
  990.         mhClobOnRmve := true;
  991.         myHand := NewHandle(Sizeof(MHandler));
  992.  
  993.         mh := MHandlerHnd(myHand);
  994.         mh^^.mhNext := mhList;
  995.         mhList := MHandlerHnd(myHand);
  996.         mh^^.mhID := theMenu^^.menuID;    { get menu id number }
  997.         mh^^.mhSelect := pSelect;            { install selection handler }
  998.         mh^^.mhClobber := pClobber;        { install disposal handler }
  999.         InsertMenu(theMenu, 0);            { put menu at end of menu bar }
  1000.         DrawMenuBar;
  1001.     END;
  1002.  
  1003. {    Remove a menu handler.  This calls the handler's disposal routine}
  1004. {    and then takes the handler out of the handler list and disposes}
  1005. {    of it.}
  1006.  
  1007. {    Note that the menu MUST be deleted from the menu bar before calling}
  1008. {    the clobber proc, because the menu bar will end up filled with}
  1009. {    garbage if the menu was allocated with NewMenu (see discussion of}
  1010. {    DisposeMenu in Menu Manager section of Inside Macintosh).}
  1011.  
  1012.     PROCEDURE SkelRmveMenu;
  1013.  
  1014.         VAR
  1015.             mID : integer;
  1016.             h, h2 : MHandlerHnd;
  1017.             p : ProcPtr;
  1018.             returnflag : Boolean;
  1019.  
  1020.     BEGIN
  1021.         mID := theMenu^^.menuID;
  1022.         returnflag := false;
  1023.         IF mhlist <> NIL THEN
  1024.             BEGIN
  1025.                 IF mhList^^.mhID = mID THEN
  1026.                     BEGIN
  1027.                         h2 := mhlist;
  1028.                         mhList := h2^^.mhNext;
  1029.                     END
  1030.                 ELSE
  1031.                     BEGIN
  1032.                         h := mhList;
  1033.                         WHILE (h <> NIL) AND NOT returnflag DO
  1034.                             BEGIN
  1035.                                 h2 := h^^.mhNext;
  1036.                                 IF (h2 = NIL) THEN
  1037.                                     BEGIN
  1038.                                         h := NIL;
  1039.                                         returnflag := true;
  1040.                                     END
  1041.                                 ELSE IF h2^^.mhID = mID THEN
  1042.                                     BEGIN
  1043.                                         h^^.mhNext := h2^^.mhNext;
  1044.                                         h := NIL;
  1045.                                     END;
  1046.                                 IF h <> NIL THEN
  1047.                                     h := h2;
  1048.                             END;
  1049.                     END;
  1050.                 IF NOT returnflag THEN
  1051.                     BEGIN
  1052.                         DeleteMenu(mID);
  1053.                         DrawMenuBar;
  1054.                         p := h2^^.mhClobber;
  1055.                         IF mhClobOnRmve AND (p <> NIL) THEN
  1056.                             callpMenu(theMenu, p);
  1057.                         DisposHandle(Handle(h2));
  1058.                     END;
  1059.             END;
  1060.     END;
  1061.  
  1062. {    Install a handler for the Apple menu.}
  1063.  
  1064. {    SkelApple is called if TransSkel is supposed to handle the apple}
  1065. {    menu itself.  The title is the title of the first item.  If nil,}
  1066. {    then only desk accessories are put into the menu.  If not nil, then}
  1067. {    the title is entered as the first item, followed by a gray line,}
  1068. {    then the desk accessories.}
  1069.  
  1070.  
  1071.     PROCEDURE SkelApple;
  1072.  
  1073.         VAR
  1074.             appleTitle : Str255;
  1075.  
  1076.     BEGIN
  1077.         appleTitle := ' ';
  1078.         appleTitle[1] := char($14);
  1079.         appleID := 1;
  1080.         AppleMenu := NewMenu(appleID, appleTitle);
  1081.         IF aboutTitle <> '' THEN
  1082.             BEGIN
  1083.                 doAbout := true;
  1084.                 AppendMenu(appleMenu, aboutTitle);
  1085.                 AppendMenu(appleMenu, '(-');
  1086.                 AppleAboutProc := aboutProc;
  1087.             END;
  1088.         AddResMenu(appleMenu, 'DRVR');
  1089.         SkelMenu(appleMenu, @DoAppleItem, @DoAppleClobber);
  1090.     END;
  1091.  
  1092. { -------------------------------------------------------------------- }
  1093. {                    Window-handler interface routines                    }
  1094. { -------------------------------------------------------------------- }
  1095.  
  1096.  
  1097.  
  1098. {    Install handler for a window.  Remove any previous handler for it.}
  1099. {    Pass the following parameters:}
  1100.  
  1101. {    theWind    Pointer to the window to be handled.  Must be created by host.}
  1102. {    pMouse    Proc to handle mouse clicks in window.  The proc will be}
  1103. {            passed the point (in local coordinates), the time of the}
  1104. {            click, and the modifier flags word.}
  1105. {    pKey    Proc to handle key clicks in window.  The proc will be passed}
  1106. {            the character and the modifier flags word.}
  1107. {    pUpdate    Proc for updating window.  TransSkel brackets calls to update}
  1108. {            procs with calls to BeginUpdate and EndUpdate, so the visRgn}
  1109. {            is set up correctly.  A flag is passed indicating whether the}
  1110. {            window was resized or not.  BY CONVENTION, the entire portRect}
  1111. {            is invalidated when the window is resized.  That way, the}
  1112. {            handler's update proc can redraw the entire content region}
  1113. {            without interference from BeginUpdate/EndUpdate.  The flag}
  1114. {            is set to false after the update proc is called; the}
  1115. {            assumption is made that it will notice the resizing and}
  1116. {            respond appropriately.}
  1117. {    pActivate Proc to execute when window is activated or deactivated.}
  1118. {            A boolean is passed to it which is true if the window is}
  1119. {            coming active, false if it's going inactive.}
  1120. {    pClose    Proc to execute when mouse clicked in close box.  Useful}
  1121. {            mainly to temp window handlers that want to know when to}
  1122. {            self-destruct (with SkelRmveWind).}
  1123. {    pClobber Proc for disposal of handler's data structures}
  1124. {    pIdle    Proc to execute when no events are pending.}
  1125. {    frontOnly True if pIdle should execute on no events only when}
  1126. {            theWind is frontmost, false if executes all the time.  Note}
  1127. {            that if it always goes, everything else may be slowed down!}
  1128.  
  1129. {    If a particular procedure is not needed (e.g., key events are}
  1130. {    not processed by a handler), pass nil in place of the appropriate}
  1131. {    procedure address.}
  1132.  
  1133. {    All handler procedures may assume that the port is set correctly}
  1134. {    at the time they are called.}
  1135.  
  1136.     PROCEDURE SkelWindow;
  1137.  
  1138.         VAR
  1139.             hHand : WhandlerHnd;
  1140.  
  1141.     BEGIN
  1142.         whClobOnRmve := false;
  1143.         SkelRmveWind(theWind);
  1144.         whClobOnRmve := true;
  1145.  
  1146.         hHand := WHandlerHnd(NewHandle(Sizeof(WHandler)));
  1147.         hHand^^.whNext := whList;
  1148.         whList := hHand;
  1149.         WITH hHand^^ DO
  1150.             BEGIN
  1151.                 whWind := theWind;
  1152.                 whMouse := pMouse;
  1153.                 whKey := pKey;
  1154.                 whUpdate := pUpdate;
  1155.                 whActivate := pActivate;
  1156.                 whClose := pClose;
  1157.                 whClobber := pClobber;
  1158.                 whIdle := pIdle;
  1159.                 whFrontOnly := frontOnly;
  1160.                 whSized := false;
  1161.                 whGrow := GrowRect;
  1162.             END;
  1163.         SetPort(theWind);
  1164.     END;
  1165.  
  1166. {    Remove a window handler.  This calls the handler's disposal routine}
  1167. {    and then takes the handler out of the handler list and disposes}
  1168. {    of it.}
  1169.  
  1170. {    SkelRmveWind is also called by SkelRmveDlog.}
  1171.  
  1172.     PROCEDURE SkelRmveWind;
  1173.  
  1174.         VAR
  1175.             h, h2 : WHandlerHnd;
  1176.             returnflag : Boolean;
  1177.  
  1178.     BEGIN
  1179.         IF (whList <> NIL) THEN
  1180.             BEGIN
  1181.                 returnflag := false;
  1182.                 IF whList^^.whWind = theWind THEN
  1183.                     BEGIN
  1184.                         h2 := whlist;
  1185.                         whList := whList^^.whNext;
  1186.                     END
  1187.                 ELSE
  1188.                     BEGIN
  1189.                         h := whList;
  1190.                         WHILE (h <> NIL) AND NOT returnflag DO
  1191.                             BEGIN
  1192.                                 h2 := h^^.whNext;
  1193.                                 IF (h2 = NIL) THEN
  1194.                                     BEGIN
  1195.                                         h := NIL;
  1196.                                         returnflag := true;
  1197.                                     END
  1198.                                 ELSE IF h2^^.whWind = theWind THEN
  1199.                                     BEGIN
  1200.                                         h^^.whNext := h2^^.whNext;
  1201.                                         h := NIL;
  1202.                                     END;
  1203.                                 IF h <> NIL THEN
  1204.                                     h := h2;
  1205.                             END;
  1206.                     END;
  1207.                 IF NOT returnflag THEN
  1208.                     BEGIN
  1209.                         IF (whClobOnRmve) THEN
  1210.                             DoClobber(h2);
  1211.                         DisposHandle(Handle(h2));
  1212.                     END;
  1213.             END;
  1214.     END;
  1215.  
  1216. { -------------------------------------------------------------------- }
  1217. {                    Dialog-handler interface routines                                }
  1218. { -------------------------------------------------------------------- }
  1219.  
  1220.  
  1221.  
  1222. {    Install a dialog handler.  Remove any previous handler for it.}
  1223. {    SkelDialog calls SkelWindow as a subsidiary to install a window}
  1224. {    handler, then sets the event procedure on return.}
  1225.  
  1226. {    Pass the following parameters:}
  1227.  
  1228. {    theDialog    Pointer to the dialog to be handled.  Must be created}
  1229. {            by host.}
  1230. {    pEvent    Event-handling proc for dialog events.}
  1231. {    pClose    Proc to execute when mouse clicked in close box.  Useful}
  1232. {            mainly to dialog handlers that want to know when to}
  1233. {            self-destruct (with SkelRmveDlog).}
  1234. {    pClobber Proc for disposal of handler's data structures}
  1235.  
  1236. {    If a particular procedure is not needed, pass nil in place of}
  1237. {    the appropriate procedure address.}
  1238.  
  1239. {    All handler procedures may assume that the port is set correctly}
  1240. {    at the time they are called.}
  1241.  
  1242.     PROCEDURE SkelDialog;
  1243.  
  1244.         VAR
  1245.             wh : WHandlerHnd;
  1246.  
  1247.     BEGIN
  1248.         SkelWindow(theDialog, NIL, NIL, NIL, NIL, pClose, pClobber, NIL, false);
  1249.         wh := GetWDHandler(theDialog);
  1250.         wh^^.whEvent := pEvent;
  1251.     END;
  1252.  
  1253. {    Remove a dialog and its handler}
  1254.  
  1255.     PROCEDURE SkelRmveDlog;
  1256.  
  1257.     BEGIN
  1258.         SkelRmveWind(theDialog);
  1259.     END;
  1260.  
  1261. { -------------------------------------------------------------------- }
  1262. {                    Miscellaneous interface routines                    }
  1263. { -------------------------------------------------------------------- }
  1264.  
  1265. {    Override the default sizing limits for a window, or, if theWind}
  1266. {    is nil, reset the default limits used by SkelWindow.}
  1267.  
  1268.     PROCEDURE SkelGrowBounds;
  1269.  
  1270.         VAR
  1271.             h : WHandlerHnd;
  1272.             r : Rect;
  1273.  
  1274.     BEGIN
  1275.         IF theWind <> NIL THEN
  1276.             SetRect(growRect, hLo, vLo, hHi, vHi)
  1277.         ELSE
  1278.             BEGIN
  1279.                 h := GetWHandler(theWind);
  1280.                 IF h <> NIL THEN
  1281.                     BEGIN
  1282.                         SetRect(r, hLo, vLo, hHi, vHi);
  1283.                         h^^.whGrow := r;
  1284.                     END;
  1285.             END;
  1286.     END;
  1287.  
  1288. {    Set the event mask.}
  1289.  
  1290.     PROCEDURE SkelEventMask;
  1291.  
  1292.     BEGIN
  1293.         eventMask := mask;
  1294.     END;
  1295.  
  1296. {    Return the event mask.}
  1297.  
  1298.     PROCEDURE SkelGetEventMask;
  1299.  
  1300.     BEGIN
  1301.         mask := eventMask;
  1302.     END;
  1303.  
  1304. {    Install a background task.  If p is nil, the current task is}
  1305. {    disabled.}
  1306.  
  1307.     PROCEDURE SkelBackground;
  1308.  
  1309.     BEGIN
  1310.         pBkgnd := p;
  1311.     END;
  1312.  
  1313. {    Return the current background task.  Return nil if none.}
  1314.  
  1315.     PROCEDURE SkelGetBackground;
  1316.     BEGIN
  1317.         p := pBkgnd;
  1318.     END;
  1319.  
  1320. {    Install an event-inspecting hook.  If p is nil, the hook is}
  1321. {    disabled.}
  1322.  
  1323.     PROCEDURE SkelEventHook;
  1324.  
  1325.     BEGIN
  1326.         pEvent := p;
  1327.     END;
  1328.  
  1329.     PROCEDURE SkelGetEventHook;
  1330.  
  1331.     BEGIN
  1332.         p := pEvent;
  1333.     END;
  1334.  
  1335. {    Set the mask for event types that will be passed to dialogs.}
  1336. {    Bit 1 is always set, so that null events will be passed.}
  1337.  
  1338.     PROCEDURE SkelDlogMask;
  1339.  
  1340.     BEGIN
  1341.         dlogEventMask := BitOr(mask, 1);
  1342.     END;
  1343.  
  1344. {    Return the current dialog event mask.}
  1345.  
  1346.     PROCEDURE SkelGetDlogMask;
  1347.  
  1348.     BEGIN
  1349.         mask := dlogEventMask;
  1350.     END;
  1351. END.